package com.ruoyi.business.service.impl;

import java.util.*;
import java.util.stream.Collectors;

import com.ruoyi.business.domain.*;
import com.ruoyi.business.domain.vo.CommonReviewVO;
import com.ruoyi.business.domain.vo.HIKUserFace;
import com.ruoyi.business.service.*;
import com.ruoyi.business.timer.HikDeviceJobTimer;
import com.ruoyi.business.vo.WxDeviceConstants;
import com.ruoyi.business.weapp.WeAppConfig;
import com.ruoyi.common.core.redis.RedisCache;
import com.ruoyi.common.utils.DateUtils;
import com.ruoyi.common.utils.uuid.UUID;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.stereotype.Service;
import com.ruoyi.business.mapper.WxUserFaceMapper;
import org.springframework.transaction.annotation.Transactional;

import static com.ruoyi.business.weapp.CommonContants.REVIEW_TYPE_REPAIR;

/**
 * 人脸识别管理Service业务层处理
 * 
 * @author ruoyi
 * @date 2021-11-27
 */
@Service
public class WxUserFaceServiceImpl implements IWxUserFaceService 
{
    @Autowired
    private WxUserFaceMapper wxUserFaceMapper;

    @Autowired
    private ICommonReviewInfoService commonReviewInfoService;

    @Autowired
    private IWxUserService wxUserService;

    @Autowired
    private IWxFaceDeviceService wxFaceDeviceService;

    @Autowired
    private RedisCache redisCache;

    @Autowired
    private IAuthBindingInfoService authBindingInfoService;

    @Autowired
    private IMessageCenterService messageCenterService;

    public static final Logger log = LoggerFactory.getLogger(WxUserFaceServiceImpl.class);

    /**
     * 查询人脸识别管理
     * 
     * @param faceId 人脸识别管理主键
     * @return 人脸识别管理
     */
    @Override
    public WxUserFace selectWxUserFaceByFaceId(Long faceId)
    {
        return wxUserFaceMapper.selectWxUserFaceByFaceId(faceId);
    }

    /**
     * 查询人脸识别管理列表
     * 
     * @param wxUserFace 人脸识别管理
     * @return 人脸识别管理
     */
    @Override
    public List<WxUserFace> selectWxUserFaceList(WxUserFace wxUserFace)
    {
        return wxUserFaceMapper.selectWxUserFaceList(wxUserFace);
    }

    /**
     * 新增人脸识别管理
     * 
     * @param wxUserFace 人脸识别管理
     * @return 结果
     */
    @Override
    public int insertWxUserFace(WxUserFace wxUserFace)
    {
        wxUserFace.setCreateTime(DateUtils.getNowDate());
        return wxUserFaceMapper.insertWxUserFace(wxUserFace);
    }

    /**
     * 修改人脸识别管理
     * 
     * @param wxUserFace 人脸识别管理
     * @return 结果
     */
    @Override
    public int updateWxUserFace(WxUserFace wxUserFace)
    {
        wxUserFace.setUpdateTime(DateUtils.getNowDate());
        return wxUserFaceMapper.updateWxUserFace(wxUserFace);
    }

    /**
     * 批量删除人脸识别管理
     * 
     * @param faceIds 需要删除的人脸识别管理主键
     * @return 结果
     */
    @Override
    public int deleteWxUserFaceByFaceIds(Long[] faceIds)
    {
        List<HandleAddPersonInfo> deviceJobs = getJobListFromRedis();

        for (Long item : faceIds) {
            log.info("当前faceID" + item);
            WxUserFace wxUserFace = wxUserFaceMapper.selectWxUserFaceByFaceId(item);

            log.info("当前wxUserFace" + wxUserFace.toString());
            if (null == wxUserFace) {
                continue;
            }
            WxUser wxUser = wxUserService.selectWxUserByUserId(wxUserFace.getUserId());
            log.info("当前wxUser" + wxUser.toString());

            if (null == wxUser) {
                continue;
            }
            List<WxFaceDevice> wxFaceDevices = wxFaceDeviceService.selectWxFaceDeviceByVillageId(Long.valueOf(wxUserFace.getVillageId()));
            log.info("当前wxFaceDevices" + wxFaceDevices.toString() + "大小" + wxFaceDevices.size());

            // 海康设备
            List<WxFaceDevice> hikDevices = wxFaceDevices.stream().filter(subitem -> WxDeviceConstants.HIK_DEVICE.equals(subitem.getDeviceType())).collect(Collectors.toList());
            // 千禧设备
            List<WxFaceDevice> qianXiDevices = wxFaceDevices.stream().filter(subitem -> WxDeviceConstants.QIAN_XI_DEVICE.equals(subitem.getDeviceType())).collect(Collectors.toList());

            // 未接受成功
            if ("1".equals(wxUserFace.getDispatchStatus())) {
                log.info("deviceJobs" + deviceJobs.toString() + "大小" + deviceJobs.size());
                if (deviceJobs != null && deviceJobs.isEmpty()) {
                    deviceJobs.removeIf(next -> wxUserFace.getBindingDispatchUuids().contains(next.getId()));
                }

                List<HIKUserFace> hikJobListFromRedis = getHikJobListFromRedis();
                log.info("当前hikJobListFromRedis" + hikJobListFromRedis.toString() + "大小" + hikJobListFromRedis.size());

                Iterator<HIKUserFace> iterator = hikJobListFromRedis.iterator();
                redisCache.deleteObject("HIK_FACE_DEVICE_JOBS");
                for (WxFaceDevice device : hikDevices) {
                    log.info("处理海康任务");
                    while (iterator.hasNext()) {
                        HIKUserFace next = iterator.next();
                        log.info("海康匹配：" + next.getHikDeviceIndex() + "/" + device.getHikDeviceIndex() + "/" + next.getFaceId()  + "/" + wxUserFace.getFaceId());
                        log.info("是否匹配任务" + (next.getHikDeviceIndex().equals(device.getHikDeviceIndex()) && next.getFaceId() == wxUserFace.getFaceId()));
                        if (next.getHikDeviceIndex().equals(device.getHikDeviceIndex()) && next.getFaceId().equals(wxUserFace.getFaceId())) {
                            log.info("删除faceid任务" + wxUserFace.getFaceId());
                            iterator.remove();
                        }
                    }
                }
                log.info("设置海康任务");
                log.info(hikJobListFromRedis.size() + "//");
                List<HIKUserFace> temp = getHikJobListFromRedis();
                temp.addAll(hikJobListFromRedis);
                if (!temp.isEmpty()) {
                    redisCache.setCacheList("HIK_FACE_DEVICE_JOBS", temp);
                }
            }

            // 已成功接受
            if ("2".equals(wxUserFace.getDispatchStatus())) {
                for (WxFaceDevice device : qianXiDevices) {
                    String bindingDispatchUuids = wxUserFace.getBindingDispatchUuids();
                    List<String> collects = Arrays.stream(bindingDispatchUuids.split(",")).collect(Collectors.toList());
                    for (String uuidItem : collects) {
                        HandleAddPersonInfo handleAddPersonInfo = new HandleAddPersonInfo();
                        handleAddPersonInfo.setId(uuidItem);
                        handleAddPersonInfo.setCmd("delete");
                        handleAddPersonInfo.setName(wxUserFace.getName());
                        handleAddPersonInfo.setSn(device.getSn());
                        System.out.println("添加设备任务");
                        deviceJobs.add(handleAddPersonInfo);
                    }
                }
            }
        }
        System.out.println("设置设备任务");
        redisCache.deleteObject("FACE_DEVICE_JOBS");
        if (!deviceJobs.isEmpty()) {
            redisCache.setCacheList("FACE_DEVICE_JOBS", deviceJobs);
        }
        return wxUserFaceMapper.deleteWxUserFaceByFaceIds(faceIds);
    }

    /**
     * 删除人脸识别管理信息
     * 
     * @param faceId 人脸识别管理主键
     * @return 结果
     */
    @Override
    public int deleteWxUserFaceByFaceId(Long faceId)
    {
        return wxUserFaceMapper.deleteWxUserFaceByFaceId(faceId);
    }

    public void handleFailFaceList(List<HIKUserFace> list) {
        for (HIKUserFace item : list) {
            WxUserFace wxUserFace = this.selectWxUserFaceByFaceId(item.getFaceId());
            wxUserFace.setDispatchStatus("100");
            wxUserFace.setStatus("100");
            this.updateWxUserFace(wxUserFace);
            MessageCenter messageCenter = new MessageCenter();
            messageCenter.setTitle("人脸识别审核结果");
            messageCenter.setContent("[人脸识别]图片质量差，设备驳回，请重新新增门禁图片");
            messageCenter.setIsRead("0");
            messageCenter.setModule("人脸识别");
            messageCenter.setDestUserId(wxUserFace.getUserId().toString());
            messageCenterService.insertMessageCenter(messageCenter);
        }
    }


    @Transactional
    @Override
    public int reviewUserFace(CommonReviewVO commonReviewVO) {
        WxUserFace wxUserFace = wxUserFaceMapper.selectWxUserFaceByFaceId(commonReviewVO.getRecordId());
        if (wxUserFace == null) {
            return 0;
        }

        CommonReviewInfo commonReviewInfo = new CommonReviewInfo();
        commonReviewInfo.setOriginalStatus(wxUserFace.getStatus());
        commonReviewInfo.setReviewContent(commonReviewVO.getContent());
        commonReviewInfo.setDestStatus(commonReviewVO.getStatus());
        commonReviewInfo.setCreateBy(commonReviewVO.getUserId().toString());
        commonReviewInfo.setBusinessId(commonReviewVO.getRecordId());
        commonReviewInfo.setReviewType(REVIEW_TYPE_REPAIR);
        wxUserFace.setStatus(commonReviewVO.getStatus());

        if (commonReviewVO.getStatus().equals("0")) {
            return commonReviewInfoService.insertCommonReviewInfo(commonReviewInfo) & wxUserFaceMapper.updateWxUserFace(wxUserFace);
        }

        WxUser wxUser = wxUserService.selectWxUserByUserId(commonReviewVO.getUserId());
        if (wxUser == null) {
            return 0;
        }

        List<AuthBindingInfo> authBindingInfos = authBindingInfoService.selectAuthBindingInfoByWxUserIdAndStatus(wxUser.getUserId(), "2");

        if (authBindingInfos.size() == 0) {
            return commonReviewInfoService.insertCommonReviewInfo(commonReviewInfo) & wxUserFaceMapper.updateWxUserFace(wxUserFace);
        }

        WxFaceDevice wxFaceDevice = new WxFaceDevice();
        wxFaceDevice.setVillageId(Long.valueOf(wxUserFace.getVillageId()));
        List<WxFaceDevice> wxFaceDevices = wxFaceDeviceService.selectWxFaceDeviceList(wxFaceDevice);

        if (wxFaceDevices.size() > 0) {
            // 海康设备
            List<WxFaceDevice> hikDevices = wxFaceDevices.stream().filter(item -> WxDeviceConstants.HIK_DEVICE.equals(item.getDeviceType())).collect(Collectors.toList());
            if (hikDevices.size() > 0) {
                handleHikDevice(hikDevices, wxUserFace, authBindingInfos);
            }
            // 千禧设备
            List<WxFaceDevice> qianXiDevices = wxFaceDevices.stream().filter(item -> WxDeviceConstants.QIAN_XI_DEVICE.equals(item.getDeviceType())).collect(Collectors.toList());
            if (qianXiDevices.size() > 0) {
                handleQianXiDevice(qianXiDevices, wxUserFace, authBindingInfos);
            }
        } else {
            return 0;
        }
        return commonReviewInfoService.insertCommonReviewInfo(commonReviewInfo) & wxUserFaceMapper.updateWxUserFace(wxUserFace);
    }

    private List<HandleAddPersonInfo> getJobListFromRedis() {
        List<HandleAddPersonInfo> deviceJobs = new ArrayList<>();;

        if (redisCache.redisTemplate.hasKey("FACE_DEVICE_JOBS")) {
            List<HandleAddPersonInfo> face_device_jobs = redisCache.getCacheList("FACE_DEVICE_JOBS");
            if (null != face_device_jobs && !face_device_jobs.isEmpty()) {
                deviceJobs = face_device_jobs;
            }
        }
        return deviceJobs;
    }

    private List<HIKUserFace> getHikJobListFromRedis() {
        List<HIKUserFace> deviceJobs = new ArrayList<>();;

        if (redisCache.redisTemplate.hasKey("HIK_FACE_DEVICE_JOBS")) {
            List<HIKUserFace> face_device_jobs = redisCache.getCacheList("HIK_FACE_DEVICE_JOBS");
            if (null != face_device_jobs && !face_device_jobs.isEmpty()) {
                deviceJobs = face_device_jobs;
            }
        }
        return deviceJobs;
    }

    private void handleQianXiDevice(List<WxFaceDevice> wxFaceDevices, WxUserFace wxUserFace, List<AuthBindingInfo> authBindingInfos) {

        List<HandleAddPersonInfo> deviceJobs = new ArrayList<>();;

        if (redisCache.redisTemplate.hasKey("FACE_DEVICE_JOBS")) {
            List<HandleAddPersonInfo> tempList = redisCache.getCacheList("FACE_DEVICE_JOBS");
            if (tempList != null && !tempList.isEmpty()) {
                deviceJobs = tempList;
            }
        }

        List<String> uuids = new ArrayList<>();
        for (WxFaceDevice item : wxFaceDevices) {
            String uuid = generateUUID();
            uuids.add(uuid);
            HandleAddPersonInfo handleAddPersonInfo = new HandleAddPersonInfo();
            handleAddPersonInfo.setId(uuid);
            handleAddPersonInfo.setCmd("add");
            handleAddPersonInfo.setName(authBindingInfos.get(0).getRealName());
            handleAddPersonInfo.setSn(item.getSn());
            handleAddPersonInfo.setFacePicture(WeAppConfig.IMAGE_HOST + wxUserFace.getResource());
            System.out.println("添加设备任务");
            deviceJobs.add(handleAddPersonInfo);
        }
        wxUserFace.setBindingDispatchUuids(String.join(",", uuids));
        wxUserFace.setDispatchStatus("1");
        System.out.println("设置设备任务");
        redisCache.deleteObject("FACE_DEVICE_JOBS");
        if (!deviceJobs.isEmpty()) {
            redisCache.setCacheList("FACE_DEVICE_JOBS", deviceJobs);
        }
    }


    private void handleHikDevice(List<WxFaceDevice> wxFaceDevices, WxUserFace wxUserFace, List<AuthBindingInfo> authBindingInfos) {
        List<HIKUserFace> jobs = new ArrayList<>();
        for (WxFaceDevice item : wxFaceDevices) {
            HIKUserFace hikUserFace = new HIKUserFace();
            BeanUtils.copyProperties(wxUserFace, hikUserFace);
            hikUserFace.setHikDeviceIndex(item.getHikDeviceIndex());
            jobs.add(hikUserFace);
        }

        synchronized (this) {
            List<HIKUserFace> deviceJobs = new ArrayList<>();;

            if (redisCache.redisTemplate.hasKey("HIK_FACE_DEVICE_JOBS")) {
                List<HIKUserFace> tempList = redisCache.getCacheList("HIK_FACE_DEVICE_JOBS");
                if (tempList != null && !tempList.isEmpty()) {
                    deviceJobs = tempList;
                }
            }
            deviceJobs.addAll(jobs);
            redisCache.deleteObject("HIK_FACE_DEVICE_JOBS");
            redisCache.setCacheList("HIK_FACE_DEVICE_JOBS", deviceJobs);
        }
        wxUserFace.setDispatchStatus("1");

    }

    @Override
    public boolean dispatchManual(String faceId) {
        try {
            WxUserFace wxUserFace = selectWxUserFaceByFaceId(Long.valueOf(faceId));
            if (null == wxUserFace) {
                return false;
            }
            List<WxFaceDevice> wxFaceDevices = wxFaceDeviceService.selectWxFaceDeviceByVillageId(Long.valueOf(wxUserFace.getVillageId()));
            if (wxFaceDevices.size() == 0) {
                return false;
            }

            List<AuthBindingInfo> authBindingInfos = authBindingInfoService.selectAuthBindingInfoByWxUserIdAndStatus(wxUserFace.getUserId(), "2");
            if (authBindingInfos.size() == 0) {
                return false;
            }

            // 海康设备
            List<WxFaceDevice> hikDevices = wxFaceDevices.stream().filter(item -> WxDeviceConstants.HIK_DEVICE.equals(item.getDeviceType())).collect(Collectors.toList());
            if (hikDevices.size() > 0) {
                handleHikDevice(hikDevices, wxUserFace, authBindingInfos);
            }
            // 千禧设备
            List<WxFaceDevice> qianXiDevices = wxFaceDevices.stream().filter(item -> WxDeviceConstants.QIAN_XI_DEVICE.equals(item.getDeviceType())).collect(Collectors.toList());
            if (qianXiDevices.size() > 0) {
                handleQianXiDevice(qianXiDevices, wxUserFace, authBindingInfos);
            }

            if (updateWxUserFace(wxUserFace) == 0) {
                return false;
            }
        } catch (Exception e) {
            e.printStackTrace();
            return false;
        }
        return true;
    }

    /**
     * 28位
     * @return
     */
    public static String generateUUID(){
        int first = new Random(10).nextInt(8) + 1;
        System.out.println(first);
        int hashCodeV = UUID.randomUUID().toString().hashCode();
        if (hashCodeV < 0) {//有可能是负数
            hashCodeV = -hashCodeV;
        }
        // 0 代表前面补充0
        // 27 代表长度为27
        // d 代表参数为正数型
        return first + String.format("%027d", hashCodeV);
    }

}
